package com.good.shopping.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 异步编排 - CompletetableFuture
 *     多组任务组合 ：
 *          当任务A 执行完，任务B 执行完，第三个任务再去执行
 *                 runAfterBothAsync   无参数 无返回值
 *                 thenAcceptBothAsync 有参数 无返回值
 *                 thenCombineAsync    有参数 有返回值
 *          当任务A 执行完，任务B 其中一个执行完，第三个任务再去执行
 *                 runAfterEitherAsync 无参数 无返回值
 *                 acceptEitherAsync   有参数 无返回值
 *                 applyToEitherAsync  有参数 有返回值
 *          当等待所有任务完成，再去执行新任务
 *                  CompletableFuture.allOf(f1,f2,f3...)
 *          只有一个任务完成， 再去执行新任务
 *                  CompletableFuture.allOf(f1,f2,f3...)
 * @author shengren.yan
 * @create 2022-03-01
 */
public class ThreadTest4 {

    //初始化线程池
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {

        // 任务A
        CompletableFuture<String> future6 = CompletableFuture.supplyAsync(() -> {
            System.out.println("组1启动了。。。。" + Thread.currentThread().getId());
//            try {
//                Thread.sleep(3000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
            System.out.println("组1结束了。。。。" + Thread.currentThread().getId());
            return "任务A参数";
        }, executor);

        // 任务B
        CompletableFuture<String> future7 = CompletableFuture.supplyAsync(() -> {
            System.out.println("组2启动了。。。。" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("组2结束了。。。。" + Thread.currentThread().getId());
            return "任务B参数";
        }, executor);

        // 测试1 ：A线程、B线程 都执行完，在执行第三个任务线程  runAfterBothAsync 无参数 无返回值
//        future6.runAfterBothAsync(future7,()->{
//            System.out.println("任务三开始。。。");
//        },executor);
//        System.out.println("主线程得到：结果：" );
//        System.out.println("main......end.....");


        // 测试2 ：A线程、B线程 都执行完，在执行第三个任务线程  thenAcceptBothAsync 有参数 无返回值
//        future6.thenAcceptBothAsync(future7,(f1,f2)->{
//            // 可以获取 任务A、任务B的参数
//            System.out.println("任务三开始。。。参数："+ f1 + f2);
//        },executor);
//        System.out.println("主线程得到：结果：" );
//        System.out.println("main......end.....");

        // 测试3 ：A线程、B线程 都执行完，在执行第三个任务线程  thenCombineAsync 有参数 有返回值
//        CompletableFuture<String> future8 = future6.thenCombineAsync(future7, (f1, f2) -> {
//            // 可以获取 任务A、任务B的参数
//            System.out.println("任务三开始。。。参数：" + f1 + f2);
//            return "任务C参数" + f1 + f2;
//        }, executor);
//        System.out.println("主线程得到：结果：" + future8.get() );
//        System.out.println("main......end.....");



        // 测试4 ：A线程、B线程 其中有一个执行完，在执行第三个任务线程  runAfterEitherAsync 无参数 无返回值
//       future6.runAfterEitherAsync(future7, () -> {
//            System.out.println("任务三开始。。。参数：");
//        }, executor);
//        System.out.println("主线程得到：结果：" );
//        System.out.println("main......end.....");

        // 测试5 ：A线程、B线程 其中有一个执行完，在执行第三个任务线程  acceptEitherAsync 有参数 无返回值
//        future6.acceptEitherAsync(future7, (res) -> {
//            // 可以获取 任务A、任务B的其中 一个 参数
//            System.out.println("任务三开始。。。参数："+ res);
//        }, executor);
//        System.out.println("主线程得到：结果：" );
//        System.out.println("main......end.....");

        // 测试5 ：A线程、B线程 其中有一个执行完，在执行第三个任务线程  applyToEitherAsync 有参数 有返回值
//        CompletableFuture<String> future9 = future6.applyToEitherAsync(future7, (res) -> {
//            // 可以获取 任务A、任务B的其中 一个 参数
//            System.out.println("任务三开始。。。参数：" + res);
//            return "任务C参数" + res;
//        }, executor);
//        System.out.println("主线程得到：结果："+ future9.get() );
//        System.out.println("main......end.....");



        CompletableFuture<String> future11 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询信息1");
            return "信息1";
        }, executor);
        CompletableFuture<String> future12 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询信息2");
            return "查询信息2";
        }, executor);
        CompletableFuture<String> future13 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询信息3");
            return "查询信息3";
        }, executor);

        // 测试6 ：当等待所有任务完成，再去执行新任务
//        CompletableFuture<Void> All = CompletableFuture.allOf(future11, future12, future13,future7,future6);
//        // All.get() 会有阻塞，其他线程都执行完，再执行后面的内容，没有All.get()，不会阻塞，会异步执行下面内容
////        All.get();
//        System.out.println("main......end.....");
//        System.out.println(future11.get() + future13.get() + future7.get() );

        // 测试7 ：只有一个任务完成， 再去执行新任务
        CompletableFuture<Object> any = CompletableFuture.anyOf(future11, future12, future13, future7, future6);
        // All.get() 会有阻塞 ，看其他任务，只有有一个完成，就执行下面内容
        any.get();
        System.out.println("main......end....." + any.get());
        System.out.println(future11.get() + future13.get() + future7.get() );

    }

}
